﻿using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Serialization;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using System.Linq;
using System.Reflection;
using UnityEditor;
#endif

namespace Puerts
{
    public delegate void ModuleInit(JsBehaviour monoBehaviour);

    [Serializable]
    public struct JsArg
    {
        public string name;
        public Object value;
    }
    ///jsBehaviour 只用来在编辑器里挂载数据,update等逻辑将统一在jsmanaer下管理,以减少跨语言调度
    public class JsBehaviour : MonoBehaviour
    {
        public TypeScript module; //可配置加载的js模块

        public Action _jsAwake;
        public Action _jsStart;
        public Action _jsOnDisable;
        public Action _jsOnEnable;
        public Action _jsOnDestroy;

        protected static JsEnv jsEnv;
        protected static bool jsEnvInitialized = false;
        
        ///传递给js 的参数
        public JsArg[] args;

        protected virtual void Awake()
        {
            if (module !=null)
            {
                if (jsEnv != null && jsEnvInitialized)
                {
                    InitAwake();
                }
                else
                {
                    StartCoroutine(delayStart());
                }
            }
        }

        IEnumerator delayStart()
        {
            while (jsEnv == null || !jsEnvInitialized)
            {
                yield return new WaitForEndOfFrame();
            }
            InitAwake();
            Start();
        }

        public void InitAwake()
        {
            var init = jsEnv.Eval<ModuleInit>($"require('{module.module}').init;");
            init?.Invoke(this);
            _jsAwake?.Invoke();
        }

        protected virtual void Start()
        {
            if(jsEnvInitialized)
                _jsStart?.Invoke();
            else 
                Debug.Log(JsManager.Instance.name + " Initializing");
        }

        public Object GetArg(string propertyName)
        {
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i].name == propertyName)
                {
                    return args[i].value;
                }
            }
            return null;
        }

        public Object[] GetArgs(string listName)
        {
            var objectIdList = new List<int>();
            for (var i = 0; i < args.Length; i++)
            {
                if (args[i].name == listName)
                {
                    objectIdList.Add(i);
                }
            }
            if (objectIdList.Count == 0)
            {
                return null;
            }
            var objectArray = new Object[objectIdList.Count];
            for (var i = 0; i < objectIdList.Count; i++)
            {
                objectArray[i] = args[i].value;
            }
            return objectArray;
        }

        protected virtual void OnDisable()
        {
            _jsOnDisable?.Invoke();
        }

        protected virtual void OnEnable()
        {
            _jsOnEnable?.Invoke();
        }

        protected virtual void OnDestroy()
        {
            _jsOnDestroy?.Invoke();
            _jsAwake = null;
            _jsStart = null;
            _jsOnDisable = null;
            _jsOnEnable = null;
            _jsOnDestroy = null;
        }
    }
}